﻿Imports System.IO
Imports System.Xml.Serialization
Imports System.Collections.Specialized

Public NotInheritable Class FileHandler

    Private Sub New()
    End Sub

    Shared ReadOnly APPDATAPATH As String = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), Application.ProductName)
    Shared ReadOnly SETTINGSFILE As String = Path.Combine(APPDATAPATH, "Settings.xml")
    Shared ReadOnly PROFILEPATH As String = Path.Combine(APPDATAPATH, "Profiles")

    Public Shared Function IsNameValid(ByVal fileName As String) As Boolean
        For Each c As Char In Path.GetInvalidFileNameChars().ToArray
            If fileName.ToCharArray.Contains(c) Then
                Return False
            End If
        Next c
        Return True
    End Function

#Region " ApplicationSettings Handling "

    Public Shared Sub SaveOptions(ByVal appSettings As ApplicationSettings)
        If Not Directory.Exists(APPDATAPATH) Then
            Directory.CreateDirectory(APPDATAPATH)
        End If
        Dim formatter As New XmlSerializer(GetType(ApplicationSettings))
        Using stream As New StreamWriter(SETTINGSFILE, False, System.Text.Encoding.UTF8)
            formatter.Serialize(stream, appSettings)
        End Using
    End Sub

    Public Shared Sub LoadOptions(ByRef appSettings As ApplicationSettings)
        If Not Directory.Exists(APPDATAPATH) Then
            Directory.CreateDirectory(APPDATAPATH)
        End If
        If Not File.Exists(SETTINGSFILE) Then
            appSettings = New ApplicationSettings
            Exit Sub
        End If
        Dim formatter As New XmlSerializer(GetType(ApplicationSettings))
        Using stream As New StreamReader(SETTINGSFILE, System.Text.Encoding.UTF8)
            appSettings = DirectCast(formatter.Deserialize(stream), ApplicationSettings)
        End Using
    End Sub

#End Region

#Region " GameProfile Handling "

    Public Shared Function GetProfileFileName(ByVal profileName As String) As String
        Return Path.Combine(PROFILEPATH, profileName & ".profile")
    End Function

    Public Shared Function GetProfileNames() As StringCollection
        If Not Directory.Exists(APPDATAPATH) Then
            Directory.CreateDirectory(APPDATAPATH)
        End If
        If Not Directory.Exists(PROFILEPATH) Then
            Directory.CreateDirectory(PROFILEPATH)
        End If
        Dim names As New StringCollection
        For Each file As String In Directory.GetFiles(PROFILEPATH, "*.profile")
            names.Add(Path.GetFileNameWithoutExtension(file))
        Next file
        Return names
    End Function

    Public Shared Function DeleteProfile(ByVal profileName As String) As Boolean
        Dim fileName As String = GetProfileFileName(profileName)
        Try
            File.Delete(fileName)
        Catch ex As IOException
            My.Application.Log.WriteException(ex)
            Return False
        End Try
        Return True
    End Function

    Public Shared Sub SaveProfile(ByVal profile As GameProfile)
        Dim fileName As String = GetProfileFileName(profile.Name)
        If Not Directory.Exists(APPDATAPATH) Then
            Directory.CreateDirectory(APPDATAPATH)
        End If
        If Not Directory.Exists(PROFILEPATH) Then
            Directory.CreateDirectory(PROFILEPATH)
        End If
        Dim formatter As New XmlSerializer(GetType(GameProfile))
        Using stream As New StreamWriter(fileName, False, System.Text.Encoding.UTF8)
            formatter.Serialize(stream, profile)
        End Using
    End Sub

    Public Shared Function LoadProfile(ByVal profileName As String) As GameProfile
        Return LoadProfileByFileName(GetProfileFileName(profileName))
    End Function

    Public Shared Function LoadProfileByFileName(ByVal fileName As String) As GameProfile
        Dim profile As New GameProfile
        If Not Directory.Exists(APPDATAPATH) Then
            Directory.CreateDirectory(APPDATAPATH)
        End If
        If Not Directory.Exists(PROFILEPATH) Then
            Directory.CreateDirectory(PROFILEPATH)
        End If
        If Not File.Exists(SETTINGSFILE) Then
            Return New GameProfile
        End If
        Dim formatter As New XmlSerializer(GetType(GameProfile))
        Using stream As New StreamReader(fileName, System.Text.Encoding.UTF8)
            profile = DirectCast(formatter.Deserialize(stream), GameProfile)
        End Using
        Return profile
    End Function

    Public Shared Sub RunProfile(ByVal profileName As String)
        Dim args As New System.Text.StringBuilder
        Dim options As New ApplicationSettings
        Dim profile As New GameProfile
        LoadOptions(options)

        profile = LoadProfile(profileName)
        If profile.MemoryCard1 <> String.Empty Then
            args.Append(String.Format("-a0,""{0}"" ", profile.MemoryCard1))
        End If
        If profile.MemoryCard2 <> String.Empty Then
            args.Append(String.Format("-a1,""{0}"" ", profile.MemoryCard1))
        End If
        Select Case profile.PadMode
            Case 1 : args.Append("-p0 ")
            Case 2 : args.Append("-p1 ")
            Case 3 : args.Append("-p2 ")
            Case 4 : args.Append("-p3 ")
            Case Else ' Use the default settings
        End Select
        If profile.DiscLocation <> String.Empty Then
            args.Append(String.Format("""{0}"" ", profile.DiscLocation))
        End If
        If profile.PatchFile <> String.Empty Then
            args.Append(String.Format("""{0}"" ", profile.PatchFile))
        End If

        Dim proc As New Process
        proc.StartInfo.FileName = options.PsxfinExePath
        proc.StartInfo.Arguments = args.ToString
        proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(options.PsxfinExePath)
        proc.Start()
        Select Case options.CpuPriority
            Case 0 : proc.PriorityClass = ProcessPriorityClass.RealTime
            Case 1 : proc.PriorityClass = ProcessPriorityClass.High
            Case 2 : proc.PriorityClass = ProcessPriorityClass.AboveNormal
            Case 3 : proc.PriorityClass = ProcessPriorityClass.Normal
            Case 4 : proc.PriorityClass = ProcessPriorityClass.BelowNormal
                'Case 5 : proc.PriorityClass = ProcessPriorityClass.Idle
            Case Else
        End Select
        If options.HideLogWindow Then
            NativeMethods.HideWindow(options.PsxfinExePath)
        End If

        Dim x As Integer = Integer.Parse(options.WindowSize.Split("x"c)(0))
        Dim y As Integer = Integer.Parse(options.WindowSize.Split("x"c)(1))
        NativeMethods.ResizeWindow("pSX", x, y)
    End Sub

#End Region

End Class
